﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using MediaPortal.GUI.Library;

namespace MediaPortal.Plugins.Trailers.Providers
{
  public class Gametrailers : TrailerProviderBase
  {
    
    #region Gametrailer Custom Feeds

    private const string urlBase = "http://www.gametrailers.com/rssgenerate.php?";
    private const string xmlNamespace = "http://www.gametrailers.com/rssexplained.php";
    private const string urlRSSLatest150 = urlBase + "?s1=&type[trailer]=on&vidformat[wmv]=on&quality[hd]=on&quality[sd]=on&orderby=newest&limit=150";
    private const string urlRSSLatest150_mov = urlBase + "?s1=&type[trailer]=&vidformat[mov]=on&quality[hd]=on&quality[sd]=on&orderby=newest&limit=150";
    private const string urlDetails = urlBase + "vidformat[wmv]=on&vidformat[mov]=on&game1id=";
    private const string urlVideo = "http://trailers.gametrailers.com/gt_vault/";
    
    #endregion

    #region TrailerProviderBase overrides

    public override string ProviderId()
    {
      return "2";
    }

    public override string ProviderName()
    {
      return "GT GameTrailers.Com";
    }

    public override string ProviderImage()
    {
      return "";
    }

    public override Index GetIndex()
    {
      Index rtIndex = new Index();
      rtIndex.Add(new IndexItem("Featured: Latest", "/latest", true));
      rtIndex.Add(new IndexItem("Latest: PC", "pc", true));
      rtIndex.Add(new IndexItem("Latest: Xbox 360", "xb360", true));
      rtIndex.Add(new IndexItem("Latest: Sony PS3", "ps3", true));
      rtIndex.Add(new IndexItem("Latest: Sony PSP", "psp", true));
      rtIndex.Add(new IndexItem("Latest: Nintendo Wii", "wii", true));
      rtIndex.Add(new IndexItem("Latest: Nintendo DS", "ds", true));
      return rtIndex;
    }

    public override Index GetIndex(string key)
    {
      return fetchIndex(key);
    }

    public override Trailer GetDetails(string key)
    {
      return fetchDetails(key);
    }

    #endregion

    private Index fetchIndex(string key)
    {
      Index items = new Index();
      string url = string.Empty;

      switch (key)
      {
        case "/latest":
          url = urlRSSLatest150;
          break;
        default:
          url = urlRSSLatest150 + "&favplats[" + key + "]=" + key;
          break;
      }
      
      List<string> trailers = getRSSTrailerIndex(url);
      foreach (string trailer in trailers)
      {
        Trailer t = Trailers[trailer];
        IndexItem item = new IndexItem();
        item.Key = trailer;
        item.Label = t.Title;
        item.Image = t.Thumb;

        items.Add(item);
      }
       return items;
    }

    private List<string> getRSSTrailerIndex(string url)
    {
      List<string> trailers = new List<string>();

      XmlNode Root = GetXml(url);
      if (Root == null)
      {
        Log.Error("[MyTrailers][Gametrailers] No RSS Found.");
        return null;
      }

      XmlNamespaceManager nsmgr = new XmlNamespaceManager(Root.OwnerDocument.NameTable);
      nsmgr.AddNamespace("exInfo", xmlNamespace);

      foreach (XmlNode tNode in Root.SelectNodes("//rss/channel/item"))
      {
        string key = tNode.SelectSingleNode("exInfo:gameID", nsmgr).InnerText;
        string guid = tNode.SelectSingleNode("guid").InnerText;
        Trailer trailer = Trailers.Set(key);
        if (!trailers.Contains(key))
        {
          trailers.Add(key);
          trailer.Title = tNode.SelectSingleNode("exInfo:gameName", nsmgr).InnerText;
          trailer.Type = Trailer.TrailerType.Game;
        }
      }

      return trailers;
    }

    private Trailer fetchDetails(string key)
    {
      Trailer trailer = Trailers.Set(key);
      string url = urlDetails + key;
      XmlNode Root = GetXml(url);
      if (Root == null)
      {
        Log.Error("[MyTrailers][Gametrailers] No Details RSS Found.");
        return null;
      }

      XmlNamespaceManager nsmgr = new XmlNamespaceManager(Root.OwnerDocument.NameTable);
      nsmgr.AddNamespace("exInfo", xmlNamespace);

      XmlNodeList TrailerNodes = Root.SelectNodes("//rss/channel/item");

      if (TrailerNodes.Count > 0) {
        string detailurl = TrailerNodes[0].SelectSingleNode("exInfo:gameURL", nsmgr).InnerText;
        string details = GetString(detailurl);

        // Description
        Regex regEx = new Regex(@"<div class=""Description"">(.+?)</div>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        Match match = regEx.Match(details);
        if (match.Success)
          trailer.Description = match.Groups[1].Value.Trim();

        // Publisher
        regEx = new Regex(@"Publisher:</span>.+?gamepage_gameinfo_normal_link"">(.*?)</a></span>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        match = regEx.Match(details);
        if (match.Success)
          trailer.Studio = match.Groups[1].Value.Trim();

        // Developer
        regEx = new Regex(@"Developer:</span>.+?gamepage_gameinfo_normal_link"">(.*?)</a></span>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        match = regEx.Match(details);
        if (match.Success)
          trailer.Director = match.Groups[1].Value.Trim();

        // Genres
        regEx = new Regex(@"Genres:</span>.+?gameinfo_normal_text"">(.*?)</span>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        match = regEx.Match(details);
        if (match.Success) {
          string[] genres = match.Groups[1].Value.Split(',');
          foreach (string genre in genres) {
            trailer.Genres.Add(genre.Trim());
          }
        }

        // Platform
        regEx = new Regex(@"plat_(.+?)_default\.gif", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        MatchCollection matches = regEx.Matches(details);
        foreach (Match m in matches) {
          trailer.Cast.Add(m.Groups[1].Value);
        }

        // Releasedate
        // @todo this is not working as expected
        regEx = new Regex(@"Release\sDate:</span>.+?gameinfo_normal_text"">(.+?)</span>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        match = regEx.Match(details);
        if (match.Success) {
          try {
            trailer.ReleaseDate = DateTime.ParseExact(match.Groups[1].Value.Trim(), "M/d/yyyy", null);
          }
          catch { }
        }

      }

      foreach (XmlNode tNode in TrailerNodes)
      {
        string guid = tNode.SelectSingleNode("guid").InnerText;
        string label = tNode.SelectSingleNode("exInfo:movieTitle", nsmgr).InnerText;
        string img = tNode.SelectSingleNode("exInfo:image", nsmgr).InnerText;
        string tmp = tNode.SelectSingleNode("pubDate").InnerText;
        string desc = tNode.SelectSingleNode("description").InnerText;

        DateTime date = DateTime.Parse(tmp.Substring(0,tmp.Length-3) + " -04");
        VideoQuality quality;

        bool isHD = Regex.IsMatch(label, @"\s(HD|HD \(Cam\))$", RegexOptions.IgnoreCase | RegexOptions.Singleline);

        if (isHD) {
          quality = VideoQuality.HD;
          label = Regex.Replace(label, @"\s(HD$|HD\s)", "", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        }
        else {
          quality = VideoQuality.SD;
        }
      
        // Get existing/new video object by label
        Video video = trailer.Media.Set(label.Trim());
        video.Date = date;
        video.Thumb = img;
        video.Description = desc;
                
        foreach (XmlNode file in tNode.SelectNodes("exInfo:fileType[type='wmv']", nsmgr))
        {
          // Add the current quality to the video
          video.Size[quality] = getMovieUri(file.SelectSingleNode("link").InnerText);
          //Log.Debug("Added video for {0}, quality: {1}, url: {2}", label, quality.ToString(), video.Size[quality]);
        }
      }
      return trailer;
    }

    private Uri getMovieUri(string url) {
      string data = GetString(url);
      Regex regEx = new Regex(@"http://trailers.gametrailers.com/gt_vault/(.+?)(?=\"")", RegexOptions.IgnoreCase | RegexOptions.Singleline);
      MatchCollection matches = regEx.Matches(data);
      string rtn = string.Empty;
      if (matches.Count > 0)
        rtn = matches[0].Value;
      return new Uri(rtn);
    }

  }
}
